package com.web.base.service.impl;

import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.dbutils.BasicRowProcessor;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;

import com.web.base.service.BaseService;
import com.web.util.db.ConnectionManager;

public class BaseServiceImpl implements BaseService {

	protected Connection conn = null;

	protected Connection connect() throws SQLException, IOException {
		if (this.conn == null || this.conn.isClosed()) {
			this.conn = ConnectionManager.getConnection();
		}

		return this.conn;
	}

	protected void release() {
		if (this.conn != null) {
			try {
				this.conn.close();
			} catch (SQLException e) {
				
			}
		}
	}

	@Override
	public int save(String sql, Object... args) throws SQLException, IOException {
		return this.update(sql, args);
	}

	@Override
	public int update(String sql, Object... args) throws SQLException, IOException {
		try {
			this.connect();
			return new QueryRunner().update(this.conn, sql, args);
		} finally {
			this.release();
		}
	}

	@Override
	public int delete(String sql, Object... args) throws SQLException, IOException {
		return this.update(sql, args);
	}

	@Override
	public List<Map<String, Object>> findAll(String sql, Object... args) throws SQLException, IOException {
		try {
			this.connect();
			return new QueryRunner().query(this.conn, sql, new MapListHandler(), args);
		} finally {
			this.release();
		}
	}

	@Override
	public <T> List<T> findAll(Class<T> clazz, String sql, Object... args) throws SQLException, IOException {
		try {
			this.connect();
			return new QueryRunner().query(this.conn, sql, new BeanListHandler<T>(clazz), args);
		} finally {
			this.release();
		}
	}

	@Override
	public Map<String, Object> findObject(String sql, Object... args) throws SQLException, IOException {
		try {
			this.connect();
			return new QueryRunner().query(this.conn, sql, new MapHandler(), args);
		} finally {
			this.release();
		}
	}

	@Override
	public <T> T findObject(Class<T> clazz, String sql, Object... args) throws SQLException, IOException {
		try {
			this.connect();
			return new QueryRunner().query(this.conn, sql, new BeanHandler<T>(clazz), args);
		} finally {
			this.release();
		}
	}

	@Override
	public List<Map<String, Object>> findPagingList(String sql, final int start, final int limit, Object... args)
	        throws SQLException, IOException {
		try {
			this.connect();
			return new QueryRunner().query(this.conn, sql, new ResultSetHandler<List<Map<String, Object>>>() {
				@Override
				public List<Map<String, Object>> handle(ResultSet rs) throws SQLException {
					List<Map<String, Object>> retList = new ArrayList<Map<String, Object>>();
					int index = 0;
					BasicRowProcessor processor = new BasicRowProcessor();

					while (rs.next()) {
						if (index >= start && index < start + limit) {
							Map<String, Object> record = processor.toMap(rs);
							retList.add(record);
						} else if (index >= start + limit) {
							break;
						}
						index++;
					}

					return retList;
				}
			}, args);
		} finally {
			this.release();
		}
	}

	@Override
	public <T> List<T> findPagingList(final Class<T> clazz, String sql, final int start, final int limit,
	        Object... args) throws SQLException, IOException {
		try {
			this.connect();
			return new QueryRunner().query(this.conn, sql, new ResultSetHandler<List<T>>() {
				@Override
				public List<T> handle(ResultSet rs) throws SQLException {
					List<T> retList = new ArrayList<T>();
					BasicRowProcessor processor = new BasicRowProcessor();

					try {
						int index = 0;
						while (rs.next()) {
							if (index >= start && index < start + limit) {
								T record = processor.toBean(rs, clazz);
								retList.add(record);
							} else if (index >= start + limit) {
								break;
							}
							index++;
						}
					} catch (SecurityException e) {
						e.printStackTrace();
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
					}

					return retList;
				}
			}, args);
		} finally {
			this.release();
		}
	}
}
